package com.wang.mvchain.common.util;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;

/**
 * 各种加密工具 md5 sha256
 * 
 * @author zjx
 *
 */
public class EncryptUtil
{
	/**
	 * 加密字符串
	 * 
	 * 加密算法$随机数$密文(加密算法加密(明文+随机数))
	 * 
	 * sha256$abcd$sha256(11111abcd)
	 * 
	 * @param souStr
	 * @return
	 */
	public String encodeStr(String souStr)
	{
		/* 分隔符 */
		String split = "$";
		/* 加密算法 */
		String encType = "sha256" ; 
		/* 随机数
		 * 生成指定位数的随机数(字母+数字)
		 *  */
		RegexUtil regexUtil = new RegexUtil() ; 
		String randStr = regexUtil.proccedRandString(32);
		
		String jiamaHead = encType + split + randStr + split ; 
		
		/* 加密字符串 */
		String jiamiStr = DigestUtils.sha256Hex(souStr + randStr); 
		return jiamaHead + jiamiStr;
	}
	
	/**
	 * 对比加密字符串
	 * 
	 * 拿着明文再加密一次,比对密文
	 * 
	 * 加密算法$随机数$密文(加密算法加密(明文+随机数))
	 * @param souStr
	 * @return
	 */
	public boolean checkStr(String souStr,String encodeStr)
	{
		/* 分隔符 */
		String split = "$";
		/* 加密算法 */
		String encType = "sha256" ; 
		/* 取随机数 
		 * 按照$拆分
		 * 0:加密算法
		 * 1:随机数
		 * 2:加密后的部分字符串(用不到)
		 * */
		String[] encodeStrs = encodeStr.split("\\"+split);
		/* 拆分后的字符串我只使用了第2个 */
		if(encodeStrs.length == 3)
		{
			/* 传入的密码必须含$ */
			/* 拼装结果的部分字符串 */
			String jiamaHead = encType + split + encodeStrs[1] + split ;
			/* 加密字符串 */
			String jiamiStr = DigestUtils.sha256Hex(souStr + encodeStrs[1]); 
			/* 拼装最终的字符串
			 * 加密算法$随机数$密文(加密算法加密(明文+随机数)) */
			String finalStr = jiamaHead + jiamiStr ; 
			
			/* 验证明文是否一致 */
			return finalStr.equalsIgnoreCase(encodeStr);
		}
		return false ; 
	}

	private static String bytArrayToHex(byte[] a)
	{
		StringBuilder sb = new StringBuilder();
		for (byte b : a)
			sb.append(String.format("%02x", b & 0xff));
		return sb.toString();
	}

	/**
	 * 使用加密,与php的算法一致
	 * 
	 * @param data
	 * @param key
	 * @return
	 */
	public static String BtcChinaHmacSHA1(String data, String key)
	{
		String result = "";

		try
		{
			// get an hmac_sha1 key from the raw key bytes
			SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(),
					"HmacSHA1");

			// get an hmac_sha1 Mac instance and initialize with the signing key
			Mac mac = Mac.getInstance("HmacSHA1");
			mac.init(signingKey);

			// compute the hmac on input data bytes
			byte[] rawHmac = mac.doFinal(data.getBytes());

			result = bytArrayToHex(rawHmac);
		} catch (Exception e)
		{
			ConstatFinalUtil.SYS_LOG.error("加密算法失败," + data + "-->" + key, e);
		}
		return result;
	}

	/**
	 * 使用加密,与php的算法一致
	 * 
	 * @param data
	 * @param key
	 * @return
	 */
	public static String hmacSHA512(String data, String key)
	{
		String result = "";
		byte[] bytesKey = key.getBytes();
		final SecretKeySpec secretKey = new SecretKeySpec(bytesKey,
				"HmacSHA512");
		try
		{
			Mac mac = Mac.getInstance("HmacSHA512");
			mac.init(secretKey);
			final byte[] macData = mac.doFinal(data.getBytes());
			byte[] hex = new Hex().encode(macData);
			result = new String(hex, "ISO-8859-1");
		} catch (Exception e)
		{
			ConstatFinalUtil.SYS_LOG.error("加密算法失败," + data + "-->" + key, e);
		}
		return result;
	}

	/**
	 * 使用加密,与php的算法一致
	 * 
	 * @param data
	 * @param key
	 * @return
	 */
	public static String hmacSHA384(String data, String key)
	{
		String result = "";
		byte[] bytesKey = key.getBytes();
		final SecretKeySpec secretKey = new SecretKeySpec(bytesKey,
				"HmacSHA384");
		try
		{
			Mac mac = Mac.getInstance("HmacSHA384");
			mac.init(secretKey);
			final byte[] macData = mac.doFinal(data.getBytes());
			byte[] hex = new Hex().encode(macData);
			result = new String(hex, "ISO-8859-1");
		} catch (Exception e)
		{
			ConstatFinalUtil.SYS_LOG.error("加密算法失败," + data + "-->" + key, e);
		}
		return result;
	}

	/**
	 * 使用加密,与php的算法一致
	 * 
	 * @param data
	 * @param key
	 * @return
	 */
	public static String hmacSHA256(String data, String key)
	{
		/*String result =  HmacUtils.hmacSha256Hex(data, key);
		return result ; */
		String result = "" ; 
		try
		{
			byte[] bytesKey = key.getBytes("UTF-8");
			final SecretKeySpec secretKey = new SecretKeySpec(bytesKey,
					"HmacSHA256");
			Mac mac = Mac.getInstance("HmacSHA256");
			mac.init(secretKey);
			result = Hex.encodeHexString(mac.doFinal(data.getBytes("UTF-8")));
		} catch (Exception e)
		{
			ConstatFinalUtil.SYS_LOG.error("加密算法失败," + data + "-->" + key, e);
		}
		return result;
	}
	
	/**
	 * 使用加密,与php的算法一致
	 * 
	 * @param data
	 * @param key
	 * @return
	 */
	public static byte[] hmacSHA256Byte(String data, String key)
	{
		try
		{
			byte[] bytesKey = key.getBytes("UTF-8");
			final SecretKeySpec secretKey = new SecretKeySpec(bytesKey,
					"HmacSHA256");
			Mac mac = Mac.getInstance("HmacSHA256");
			mac.init(secretKey);
			return mac.doFinal(data.getBytes("UTF-8"));
		} catch (Exception e)
		{
			ConstatFinalUtil.SYS_LOG.error("加密算法失败," + data + "-->" + key, e);
		}
		return null;
	}

	/**
	 * 使用加密,与php的算法一致
	 * 
	 * @param data
	 * @param key
	 * @return
	 */
	public static String hmacSHA1(String data, String key)
	{
		String result = "";
		byte[] bytesKey = key.getBytes();
		final SecretKeySpec secretKey = new SecretKeySpec(bytesKey, "HmacSHA1");
		try
		{
			Mac mac = Mac.getInstance("HmacSHA1");
			mac.init(secretKey);
			final byte[] macData = mac.doFinal(data.getBytes());
			byte[] hex = new Hex().encode(macData);
			result = new String(hex, "ISO-8859-1");
		} catch (Exception e)
		{
			ConstatFinalUtil.SYS_LOG.error("加密算法失败," + data + "-->" + key, e);
		}
		return result;
	}
	
	/**
	 * SHA加密
	 * @param aValue
	 * @return
	 */
	public static String digest(String aValue , String algorithm) {
		aValue = aValue.trim();
		byte value[];
		try {
			value = aValue.getBytes("UTF-8");
		} catch (UnsupportedEncodingException e) {
			value = aValue.getBytes();
		}
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("SHA");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return null;
		}
		return toHex(md.digest(value));
	}
	
	public static String toHex(byte input[]) {
		if (input == null)
			return null;
		StringBuffer output = new StringBuffer(input.length * 2);
		for (int i = 0; i < input.length; i++) {
			int current = input[i] & 0xff;
			if (current < 16)
				output.append("0");
			output.append(Integer.toString(current, 16));
		}

		return output.toString();
	}
	
	public static void main(String[] args)
	{
		EncryptUtil encryptUtil = new EncryptUtil() ; 
		String res = encryptUtil.encodeStr("111111");
		System.out.println("====>" + res);
	}
}
